#include <google/protobuf/descriptor.h>
#include <google/protobuf/message.h>
#include "protos/person.pb.h"

using namespace google::protobuf;

void PrintMessageFields(const Message& message) {
    const Descriptor* descriptor = message.GetDescriptor();
    const Reflection* reflection = message.GetReflection();

    for (int i = 0; i < descriptor->field_count(); ++i) {
        const FieldDescriptor* field = descriptor->field(i);

        std::cout << "Field: " << field->name();

        if (field->is_repeated()) {
            int size = reflection->FieldSize(message, field);
            std::cout << " (repeated, size = " << size << "):\n";
            for (int j = 0; j < size; ++j) {
                switch (field->cpp_type()) {
                    case FieldDescriptor::CPPTYPE_STRING:
                        std::cout << "  - " << reflection->GetRepeatedString(message, field, j) << "\n";
                        break;
                    // 其他类型同理处理
                    case FieldDescriptor::CPPTYPE_INT32:
                    case FieldDescriptor::CPPTYPE_INT64:
                    case FieldDescriptor::CPPTYPE_UINT32:
                    case FieldDescriptor::CPPTYPE_UINT64:
                    case FieldDescriptor::CPPTYPE_DOUBLE:
                    case FieldDescriptor::CPPTYPE_FLOAT:
                    case FieldDescriptor::CPPTYPE_BOOL:
                    case FieldDescriptor::CPPTYPE_ENUM:
                    case FieldDescriptor::CPPTYPE_MESSAGE:
                      break;
                    }
            }
        } else if (reflection->HasField(message, field)) {
            std::cout << " = ";
            switch (field->cpp_type()) {
                case FieldDescriptor::CPPTYPE_STRING:
                    std::cout << reflection->GetString(message, field);
                    break;
                case FieldDescriptor::CPPTYPE_INT32:
                    std::cout << reflection->GetInt32(message, field);
                    break;
                // 其他类型同理处理
                case FieldDescriptor::CPPTYPE_INT64:
                case FieldDescriptor::CPPTYPE_UINT32:
                case FieldDescriptor::CPPTYPE_UINT64:
                case FieldDescriptor::CPPTYPE_DOUBLE:
                case FieldDescriptor::CPPTYPE_FLOAT:
                case FieldDescriptor::CPPTYPE_BOOL:
                case FieldDescriptor::CPPTYPE_ENUM:
                case FieldDescriptor::CPPTYPE_MESSAGE:
                  break;
                }
            std::cout << "\n";
        } else {
            std::cout << " (not set)\n";
        }
    }
}

int main(){
    Person person;
    person.set_name("Alice");
    person.set_id(123);
    PrintMessageFields(person);
}
